# coding: utf-8
from django import forms

from accounts.models import User
from models import SharedAccount, MemberAccount, Deposit, Draw, Pay, DepositAndPay, Transfer
from models import DistributeMode

import tz

class AmountField(forms.FloatField):
    def __init__(self, *args, **kwargs):
        if 'label' not in kwargs:
            kwargs['label'] = u'金额(元)'
        super(AmountField, self).__init__(*args, **kwargs)

    def clean(self, value):
        value = super(AmountField, self).clean(value)
        if value <= 0:
            raise forms.ValidationError(u'金额必须大于0')
        return value

class AccountForm(forms.Form):
    name = forms.CharField(label=u'帐户名称')

    def __init__(self, *args, **kwargs):
        instance = kwargs.pop('instance', None)
        if instance is not None:
            initial = kwargs.setdefault('initial', {})
            initial.setdefault('name', instance.name)
        super(AccountForm, self).__init__(*args, **kwargs)

    def save(self, request, instance=None):
        if instance is None:
            account = SharedAccount(name=self.cleaned_data['name'], creator=request.user)
            account.add_member(MemberAccount(user=request.user)) # add current user
        else:
            account = instance
            account.name = self.cleaned_data['name']
            account.put()
        return account

class AddMemberForm(forms.Form):
    email = forms.EmailField(label=u'用户邮箱', help_text=u'输入待添加用户的邮箱')

    def __init__(self, *args, **kwargs):
        self.account = kwargs.pop('account', None)
        member = kwargs.pop('instance', None)
        if member is not None:
            initial = kwargs.setdefault('initial', {})
            initial.setdefault('email', member.user.email)
        super(AddMemberForm, self).__init__(*args, **kwargs)

    def clean_email(self):
        email = self.cleaned_data['email']
        user = User.all().filter('email = ', email).get()
        if not user:
            raise forms.ValidationError(u'不存在邮箱为%s的用户' % email)
        for member in self.account.get_members():
            if member.user.email == email:
                raise forms.ValidationError(u'该用户已经添加')
        return email

    def add_member(self):
        email = self.cleaned_data['email']
        user = User.all().filter('email = ', email).get()
        member = MemberAccount(user=user)
        self.account.add_member(member)
        return member

class EditMemberForm(forms.Form):
    name = forms.CharField(label=u'用户名称')
    #is_active = forms.BooleanField(label=u'有效', initial=True, required=False, help_text=u'标记该成员是否为活动状态')

    def __init__(self, *args, **kwargs):
        self.account = kwargs.pop('account', None)
        self.member = member = kwargs.pop('instance', None)
        if member is not None:
            initial = kwargs.setdefault('initial', {})
            initial.setdefault('name', member.name)
            #initial.setdefault('is_active', member.is_active)
        super(EditMemberForm, self).__init__(*args, **kwargs)

    def update_member(self):
        member = self.member
        member.name = self.cleaned_data['name']
        #member.is_active = self.cleaned_data['is_active']
        member.is_active = True
        member.put()
        return member

class DepositForm(forms.Form):
    member = forms.CharField(label=u'存入账户')      # just as a placeholder
    amount = AmountField()
    usage = forms.CharField(label=u'用途', required=False)
    detail = forms.CharField(label=u'备注', widget=forms.Textarea, required=False)
    time = forms.DateTimeField(label=u'时间', initial=tz.local_now)

    def __init__(self, account, current_member, *args, **kwargs):
        self.account = account
        self.current_member = current_member
        super(DepositForm, self).__init__(*args, **kwargs)

        self.fields['member'] = forms.TypedChoiceField(label=self.fields['member'].label, coerce=long,
                                        initial=current_member.id, choices=MemberAccountChoiceIterator(account))

    def save(self):
        member = MemberAccount.get_by_id(self.cleaned_data['member'])
        deposit = Deposit(
                    member=member,
                    account=self.account,
                    amount=self.cleaned_data['amount'], 
                    usage=self.cleaned_data['usage'] or u'存款',
                    detail=self.cleaned_data['detail'],
                    time=tz.utc_time(self.cleaned_data['time']),
                    creator=self.current_member,
                )
        deposit.save()
        return deposit

class MemberAccountChoiceIterator(object):
    def __init__(self, shared_account):
        self.shared_account = shared_account

    def __iter__(self):
        for member in self.shared_account.get_members():
            yield self.choice(member)

    def choice(self, member_account):
        return (member_account.id, member_account.name)

class DrawForm(DepositForm):
    member = forms.CharField(label=u'取出帐户')

    def save(self):
        member = MemberAccount.get_by_id(self.cleaned_data['member'])
        draw = Draw(member=member,
                    account=self.account,
                    amount=self.cleaned_data['amount'],
                    time=tz.utc_time(self.cleaned_data['time']),
                    creator=self.current_member,
                    usage=self.cleaned_data['usage'] or u'取款',
                    detail=self.cleaned_data['detail']
                )
        draw.save()
        return draw

DIST_MODE_CHOICES = (
        (DistributeMode.EQUAL, u'平摊'),
        (DistributeMode.PERCENT, u'按比例'),
        (DistributeMode.NUMBER, u'按数目'),
)
class PayForm(forms.Form):
    amount = AmountField()
    usage = forms.CharField(label=u'用途', help_text='例如：买菜，水电费等')
    detail = forms.CharField(label=u'备注', widget=forms.Textarea, required=False)
    time = forms.DateTimeField(label=u'时间', initial=tz.local_now)

    dist_mode = forms.ChoiceField(label=u'摊派方式', widget=forms.RadioSelect, 
                              initial=DistributeMode.EQUAL, choices=DIST_MODE_CHOICES)

    def __init__(self, account, current_member, *args, **kwargs):
        super(PayForm, self).__init__(*args, **kwargs)
        self.account, self.current_member = account, current_member
        self.members = account.get_members()

    def get_dm_data(self):
        for mem_id in self.data.getlist('member_ids'):
            mem_id = long(mem_id)
            if mem_id not in self.account.member_ids:
                continue
            percent = int(self.data.get('dm_percent_%s' % mem_id) or 0)
            num = float(self.data.get('dm_number_%s' % mem_id) or 0.0)
            yield mem_id, percent, num

    def clean_dist_mode(self):
        dist_mode = self.cleaned_data['dist_mode']
        if dist_mode == DistributeMode.PERCENT:
            try:
                total = 0
                for _, percent, _ in self.get_dm_data():
                    if percent < 0:
                        raise forms.ValidationError(u'摊派比例必须不少于0')
                    total += percent
                if total != 100:
                    raise forms.ValidationError(u'摊派比例之和必须为100')
            except (TypeError, ValueError):
                raise forms.ValidationError(u'摊派比例必须为整数')
        elif dist_mode == DistributeMode.NUMBER:
            try:
                total = 0
                for _, _, num in self.get_dm_amounts():
                    if num < 0:
                        raise forms.ValidationError(u'摊派数目必须不少于0')
                    total += num
                if total != self.cleaned_data['amount']:
                    raise forms.ValidationError(u'摊派数目之和必须等于支出金额')
            except (TypeError, ValueError):
                raise forms.ValidationError(u'摊派数目必须为数字')
        return dist_mode

    def save(self):
        pay = Pay(account=self.account,
                    creator=self.current_member,
                    amount=self.cleaned_data['amount'],
                    time=tz.utc_time(self.cleaned_data['time']),
                    dist_mode=self.cleaned_data['dist_mode'],
                    usage=self.cleaned_data['usage'],
                    detail=self.cleaned_data['detail']
                 )
        mem_ids, percents, nums = zip(*self.get_dm_data())
        if pay.dist_mode == DistributeMode.PERCENT:
            pay.dist_member_ids, pay.dist_percents = list(mem_ids), list(percents)
        elif pay.dist_mode == DistributeMode.NUMBER:
            pay.dist_member_ids, pay.dist_numbers = list(mem_ids), list(nums)
        elif pay.dist_mode == DistributeMode.EQUAL:
            pay.dist_member_ids = list(mem_ids)
        pay.save()
        return pay

class DepositAndPayForm(PayForm):
    member = forms.CharField(label=u'垫付帐户')

    def __init__(self, account, current_member, *args, **kwargs):
        super(DepositAndPayForm, self).__init__(account, current_member, *args, **kwargs)

        self.fields['member'] = forms.TypedChoiceField(label=self.fields['member'].label, coerce=long,
                                        initial=current_member.id,
                                        choices=MemberAccountChoiceIterator(account))
        self.fields.keyOrder = ['member', 'amount', 'usage', 'detail', 'time', 'dist_mode']

    def save(self):
        from_member = MemberAccount.get_by_id(self.cleaned_data['member'])
        dp = DepositAndPay(
                    member=from_member,
                    amount=self.cleaned_data['amount'],
                    account=self.account,
                    creator=self.current_member, 
                    time=tz.utc_time(self.cleaned_data['time']),
                    dist_mode=self.cleaned_data['dist_mode'],
                    usage=self.cleaned_data['usage'],
                    detail=self.cleaned_data['detail'],
            )
        mem_ids, percents, nums = zip(*self.get_dm_data())
        if dp.dist_mode == DistributeMode.PERCENT:
            dp.dist_member_ids, dp.dist_percents = list(mem_ids), list(percents)
        elif dp.dist_mode == DistributeMode.NUMBER:
            dp.dist_member_ids, dp.dist_numbers = list(mem_ids), list(nums)
        elif dp.dist_mode == DistributeMode.EQUAL:
            dp.dist_member_ids = list(mem_ids)
        dp.save()
        return dp

class TransferForm(forms.Form):
    member = forms.TypedChoiceField(label=u'转出帐户', coerce=long)
    to_member = forms.TypedChoiceField(label=u'转入帐户', coerce=long)
    amount = AmountField()
    usage = forms.CharField(label=u'用途', required=False)
    detail = forms.CharField(label=u'备注', widget=forms.Textarea, required=False)
    time = forms.DateTimeField(label=u'时间', initial=tz.local_now)

    def __init__(self, account, current_member, *args, **kwargs):
        super(TransferForm, self).__init__(*args, **kwargs)
        self.account, self.current_member = account, current_member
        self.fields['member'] = forms.TypedChoiceField(label=self.fields['member'].label, coerce=long,
                                        initial=current_member.id, choices=MemberAccountChoiceIterator(account))
        self.fields['to_member'] = forms.TypedChoiceField(label=self.fields['to_member'].label, coerce=long,
                                        initial=current_member.id, choices=MemberAccountChoiceIterator(account))

    def clean(self):
        if self.cleaned_data['member'] == self.cleaned_data['to_member']:
            self.errors['to_member'] = [u'必须转到另一个帐户']
            del self.cleaned_data['to_member']
        return self.cleaned_data

    def save(self):
        from_member = MemberAccount.get_by_id(self.cleaned_data['member'])
        to_member = MemberAccount.get_by_id(self.cleaned_data['to_member'])
        transfer = Transfer(member=from_member,
                            to_member=to_member,
                            account=self.account,
                            amount=self.cleaned_data['amount'], 
                            time=tz.utc_time(self.cleaned_data['time']),
                            usage=self.cleaned_data['usage'] or u'转账',
                            detail=self.cleaned_data['detail'],
                            creator=self.current_member)
        transfer.save()
        return transfer

